package com.mindata.blockchain.block.RLP;

import com.mindata.blockchain.block.InstructionBase;
import com.mindata.blockchain.common.util.ByteUtil;
import com.mindata.blockchain.common.util.RLP;
import com.mindata.blockchain.common.util.RLPList;

/**
 * Created by Ming on 2018/8/10.
 */
public class InstructionBaseB {

    protected static final byte[] EMPTY_BYTE_ARRAY = new byte[]{};

    private byte operation;

    private byte[] table;

    private byte[] oldJson;

    private byte[] instructionId;

    protected byte[] rlpEncoded;

    private boolean parsed = false;

    public InstructionBaseB() {
    }

    public InstructionBaseB(InstructionBase instructionBase) {
        this.operation = instructionBase.getOperation();
        this.table = instructionBase.getTable() != null ? instructionBase.getTable().getBytes() : EMPTY_BYTE_ARRAY;
        this.oldJson = instructionBase.getOldJson() != null ? instructionBase.getOldJson().getBytes() : EMPTY_BYTE_ARRAY;
        this.instructionId = instructionBase.getInstructionId() != null ? instructionBase.getInstructionId().getBytes() : EMPTY_BYTE_ARRAY;
        this.rlpEncoded = null;
    }

    public InstructionBaseB(byte[] rawData) {
        this.rlpEncoded = rawData;
    }

    private synchronized void parseRLP() {
        if (parsed)
            return;
        RLPList params = (RLPList) RLP.decode2(rlpEncoded).get(0);

        this.operation = params.get(0).getRLPData()[0];
        this.table = params.get(1).getRLPData();
        this.oldJson = params.get(2).getRLPData();
        this.instructionId = params.get(3).getRLPData();

        this.parsed = true;
    }

    public byte getOperation() {
        parseRLP();
        return operation;
    }

    public void setOperation(byte operation) {
        this.operation = operation;
    }

    public byte[] getTable() {
        parseRLP();
        return table;
    }

    public void setTable(byte[] table) {
        this.table = table;
    }

    public byte[] getOldJson() {
        parseRLP();
        return oldJson;
    }

    public void setOldJson(byte[] oldJson) {
        this.oldJson = oldJson;
    }

    public byte[] getInstructionId() {
        parseRLP();
        return instructionId;
    }

    public void setInstructionId(byte[] instructionId) {
        this.instructionId = instructionId;
    }

    public byte[] encode() {
        if (rlpEncoded == null) {

            byte[] table = encode(this.table);
            byte[] oldJson = encode(this.oldJson);
            byte[] instructionId = encode(this.instructionId);
            rlpEncoded = RLP.encodeList(encode(new byte[]{operation}), table, oldJson, instructionId);
        }
        return rlpEncoded;
    }

    public byte[] encode(byte[] var) {
        return RLP.encodeElement(var);
    }

    public InstructionBase convertToInstructionBase() {
        parseRLP();

        InstructionBase instructionBase = new InstructionBase();

        instructionBase.setOperation(getOperation());

        if (!ByteUtil.isNullOrZeroArray(getTable()))
            instructionBase.setTable(new String(getTable()));

        if (!ByteUtil.isNullOrZeroArray(getOldJson()))
            instructionBase.setOldJson(new String(getOldJson()));

        if (!ByteUtil.isNullOrZeroArray(getInstructionId()))
            instructionBase.setInstructionId(new String(getInstructionId()));

        return instructionBase;
    }

}
